<template>
  <div @click="clickItem" class="qhh-virtual-tree-check-box" :class="{'qhh-virtual-tree-check-box-reverse': preCheckbox}">
    <template v-if="preCheckbox">
      <div
        v-if="showBox"
        :class="['box',
        { 'is-checked': checked,
        'is-part-checked': indeterminate,
        'is-disabled': disabled,
        'check-box-margin': preCheckbox }]"
        :style="{width: checkBoxSize,height: checkBoxSize}"
        @click="onChecked"
      >
        <div class="box-after" :style="`background-size: ${checkBoxSize} ${checkBoxSize};background-image: url(${disabled ? checkedDisabledIcon : checkedIcon});`"></div>
        <div v-if="!checkStrictly" class="part-after" :style="`background-size: ${checkBoxSize} ${checkBoxSize};background-image: url(${disabled ? checkedPartDisabledIcon : checkedPartIcon});`"></div>
      </div>
      <div :class="['label', labelClass]" @click="onSingleChecked" @dblclick="onDBLChecked">
        <slot />
      </div>
    </template>
    <template v-else>
      <div :class="['label', labelClass]" @click="onSingleChecked" @dblclick="onDBLChecked">
        <slot />
      </div>
      <div
        v-if="showBox"
        :class="['box', { 'is-checked': checked, 'is-part-checked': indeterminate, 'is-disabled': disabled }]"
        :style="{width: checkBoxSize,height: checkBoxSize}"
        @click="onChecked"
      >
        <div class="box-after" :style="`background-size: ${checkBoxSize} ${checkBoxSize};background-image: url(${disabled ? checkedDisabledIcon : checkedIcon});`"></div>
        <div v-if="!checkStrictly" class="part-after" :style="`background-size: ${checkBoxSize} ${checkBoxSize};background-image: url(${disabled ? checkedPartDisabledIcon : checkedPartIcon});`"></div>
      </div>
    </template>
  </div>
</template>

<script>
  import { depthFirstEach } from './util.js';
  import defaultCheckedIcon from "../../assets/checked-element-ui.svg";
  import defaultCheckedDisabledIcon from "../../assets/checked-element-ui-disabled.svg";
  import defaultCheckedPartIcon from "../../assets/indeterminate-element-ui.svg";
  import defaultCheckedPartDisabledIcon from "../../assets/indeterminate-element-ui-disabled.svg";

  export default {
    model: {
      prop: 'checked',
      event: 'checked-change',
    },
    emits: ['update:checked', 'on-checked'],
    props: {
      options: {},
      labelClass: {type: String, default: ""},
      preCheckbox: {type: Boolean, default: false},
      checkBoxSize: { type: String, default: '12px'},
      checkedIcon: {type: String, default: defaultCheckedIcon },
      checkedPartIcon: {type: String, default: defaultCheckedPartIcon },
      checkedDisabledIcon: {type: String, default: defaultCheckedDisabledIcon },
      checkedPartDisabledIcon: {type: String, default: defaultCheckedPartDisabledIcon },
      checked: { type: Boolean, default: false },
      indeterminate: { type: Boolean, default: false },
      disabled: { type: Boolean, default: false },
      checkedAction: { type: String, default: 'none' },
      showCheckbox: { type: Boolean, default: false },
      isLeaf: { type: Boolean, default: true },
      showCheckboxLeafOnly: { type: Boolean, default: false },
      node: { type: Object, default: () => {} },
      checkStrictly: { type: Boolean, default: false },
      showCheckboxByKeys: {type: [Array, null], default: null}
    },
    computed: {
      showBox() {
        if (this.showCheckbox) {
          const keys = Object.keys(this.node)
          // 如果设置了showCheckboxByKeys 则判断node中是否存在showCheckboxByKeys中任意一个值
          // 如果没设置 则返回true 即全部显示
          let res = this.showCheckboxByKeys ? this.showCheckboxByKeys.some(k => keys.includes(k)) : true
          if (this.showCheckboxLeafOnly) {
            res = res && this.isLeaf;
          }
          return res;
        }
        return false;
      },
    },
    methods: {
      onChecked(e) {
        e.stopPropagation()
        if (this.disabled) return;

        this.$emit('checked-change', this.getNewChecked(this.checked));
        this.$emit('on-checked');
      },
      labelClick() {
        this.$emit('on-click-label');
      },
      onSingleChecked() {
        if (this.checkedAction === 'click' && this.showBox) this.onChecked();
        this.labelClick();
      },
      clickItem(e) {
        e.stopPropagation()
        this.$emit('on-click-item')
      },
      onDBLChecked() {
        if (this.checkedAction === 'dblclick' && this.showBox) this.onChecked();
        this.labelClick();
      },

      getNewChecked(oldChecked) {
        if (this.node.isLeaf || this.checkStrictly) {
          return !oldChecked;
        }
        let newChecked = false;
        depthFirstEach({ tree: this.node[this.options.childrenKey], options: this.options }, node => {
          if (node.isLeaf && !node[this.options.disabledKey] && !node.checked) {
            newChecked = true;
            return 'break';
          }
        });
        return newChecked;
      },
    },
  };
</script>

<style lang="scss">
  $border-color: #409eff;
.qhh-virtual-tree-check-box {
  flex: 1;
  box-sizing: border-box;
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  overflow: hidden;
  .checkbox-slot {
    width: 100%;
  }
  .label {
    cursor: pointer;
    display: flex;
    align-items: center;
    //width: 100%;
    margin-right: 4px;
    width: 100%;
    overflow: hidden;
    .count {
      font-size: 12px;
      flex-shrink: 0;
    }
  }
  .check-box-margin {
    margin: 0 8px 0 0;
  }
  .box {
    box-sizing: border-box;
    position: relative;
    width: 12px;
    height: 12px;
    border: 1px solid #dcdfe6;
    border-radius: 2px;
    cursor: pointer;
    flex-shrink: 0;
    &:hover {
      border-color: $border-color;
    }
    .box-after {
      background-position: center;
      background-repeat: no-repeat;
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      transform: scale(0);
    }

    // 子元素部分选中
    &.is-part-checked .part-after {
      background-position: center;
      background-repeat: no-repeat;
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      transform: scale(0);
    }
    &.is-checked {
      border: 0;
      & .box-after {
        transform: scale(1);
      }
    }
    &.is-part-checked {
      border: 0;
      color: $border-color;
      .part-after {
        transform: scale(1);
      }
    }
    &.is-disabled {
      background: #f2f6fc;
      color: #c0c4cc;
      border-color: #c0c4cc;
      /*> div {*/
      /*  filter: grayscale(100%);*/
      /*}*/
      &::after {
        cursor: not-allowed;
      }
    }
  }
}
  .qhh-virtual-tree-check-box-reverse {
    justify-content: left;
  }
</style>
